﻿using Frameworks;
using Network.Core;
using Network.General.Client;
using System;

namespace Client
{
    public class HeartBeatHandler
    {
        public Action onTimeout;

        private NetManager _net;
        private float _lastHeartBeatTime = 0;
        private uint _ping = 0;

        public void Init(NetManager net)
        {
            _net = net;
        }

        public void Start()
        {
            _lastHeartBeatTime = Network.Utils.Time.GetTimeSinceStartup() + Network.Math.Random.Default.Range(5.0f);

            GameManager.Instance.AddFixedUpdateListener(onUpdate);
        }

        public void Stop()
        {
            GameManager.Instance?.RemoveFixedUpdateListener(onUpdate);
        }

        private void onUpdate()
        {
            float current = Network.Utils.Time.GetTimeSinceStartup();
            if (current - _lastHeartBeatTime > 5.0f)
            {
                _lastHeartBeatTime = current;

                HeartBeatReq req = new HeartBeatReq();
                req.ping = (ushort)_ping;
                req.timestamp = (uint)Network.Utils.TimeUtils.GetTotalMillisecondsSince1970();
                _net.Send<HeartBeatRsp>(ProtoCmd.HeartBeatReq, req, onHeartBeatRsp, 15, onHeartBeatError);
            }
        }

        private void onHeartBeatRsp(uint index, HeartBeatRsp rsp)
        {
            //UnityEngine.Debug.Log("<color=yellow>Client.HeartBeatHandler.OnHeartBeatRsp</color>");

            if (rsp.ret.code == 0)
            {
                uint current = (uint)Network.Utils.TimeUtils.GetTotalMillisecondsSince1970();
                uint dt = current - rsp.timestamp;
                _ping = dt / 2;
            }
        }

        private void onHeartBeatError(NetErrorCode code)
        {
            if (code == NetErrorCode.Timeout)
            {
                Stop();
                onTimeout.Invoke();
            }
        }
    }
}